# -*- coding: utf-8 -*-
'''
@文件    :config.py
@说明    :环境配置
@时间    :2025/02/13 16:44:01
@作者    :浪晋
@版本    :1.0
'''

import os
import sys
from typing import Dict, Any, Union, List
from pathlib import Path
from functools import lru_cache
from datetime import date
from pydantic_settings import BaseSettings, SettingsConfigDict
from app.enums.settings import EnvironmentEnum


class Settings(BaseSettings):
    """系统配置类"""
    model_config = SettingsConfigDict(
        env_file='.env',
        env_file_encoding="utf-8",
        case_sensitive=True,
    )

    ENVIRONMENT: EnvironmentEnum


    # ================================================= #
    # ******************* 服务器配置 ****************** #
    # ================================================= #
    SERVER_HOST: str         # 允许访问的IP地址
    SERVER_PORT: int         # 服务端口
    RELOAD: bool             # 是否自动重启
    FACTORY: bool            # 是否使用工厂函数
    WORKERS: int             # 启动进程数
    ACCESS_LOG: bool         # 是否开启访问日志


    # ================================================= #
    # ***************** 静态文件配置 ******************* #
    # ================================================= #
    STATIC_URL: str = "/static"  # 访问路由
    STATIC_PATH: str = "static"  # 文件路径
    STATIC_NAME: str = "static"   # 目录名


    # ================================================= #
    # ******************* API文档配置 ****************** #
    # ================================================= #
    DEBUG: bool = False                 # 是否开启调试模式
    TITLE: str                          # 文档标题
    VERSION: str                        # 版本号
    DESCRIPTION: str                    # 文档描述
    SUMMARY: str | None                 # 文档概述
    ROOT_PATH: str = ""                 # 根路径
    ROOT_PATH_IN_SERVERS: bool = False  # 是否在服务器中使用根路径
    SWAGGER_CSS_URL: Path = "static/swagger-ui/swagger-ui.css"
    SWAGGER_JS_URL: Path = "static/swagger-ui/swagger-ui-bundle.js"
    REDOC_JS_URL: Path = "static/redoc/redoc.standalone.js"
    FAVICON_URL: Path = "static/favicon.png"

    # ================================================= #
    # ******************* API安全配置 ****************** #
    # ================================================= #
    SECRET_KEY: str = "vgb0tnl9d58+6n-6h-ea&u^1#s0ccp!794=krylxcjq75vzps$"  # JWT密钥
    SECURITY_HEADER_NAME: str = "Authorization"
    SECURITY_HEADER_PREFIX: str = "Bearer"
    EXPIRE_TIME: int = 60 * 60 * 24 * 30  # 过期时间，单位：秒
    PASSWORD_HASH_ALGORITHM: str = "argon2"  # 密码哈希算法

    # ================================================= #
    # ******************* 上下文管理器 ****************** #
    # ================================================= #
    CTX_LIST: List[str] = ["g", "stack"]  # 上下文管理器

    # ================================================= #
    # ********************* 日志配置 ******************* #
    # ================================================= #
    LOGGER_SINK: Any = sys.stdout  # date.today().strftime(r'%Y-%m-%d.log') 
    LOGGER_LEVEL: str = "DEBUG"                                              # 日志级别
    LOGGER_FORMAT: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> <cyan>{extra[x_requests_id]}</cyan> <level>{message}</level>"
    LOGGER_INTERCEPT: bool = False                                 # 是否接管其他模块的日志
    IGNORE_OPERATION_LOG: bool = False                              # 忽略记录操作日志
    IGNORE_OPERATION_FUNCTION: List[str] = ["custom_swagger_ui_html", "custom_redoc_html", "log_list", "log_detail"]                       # 忽略要记录操作日志的函数
    LOGGER_OUTPUT_CONSOLE: bool = True                              # 是否输出到控制台
    LOGGER_OUTPUT_DATABASE: bool = False                             # 是否输出到数据库

    # ================================================= #
    # ******************** ORM配置 ******************* #
    # ================================================= #
    ORM_MODELS: List[str] = ['app.models', 'aerich.models']
    ORM_ENGINE: str = "mysql"


    # ================================================= #
    # ******************** Sqlite配置 ******************* #
    # ================================================= #
    SQLITE_DB_PATH: str = "db"
    SQLITE_DB_NAME: str = "db.sqlite3"


    # ================================================= #
    # ******************** MySql配置 ******************* #
    # ================================================= #
    MYSQL_HOST: str = "loaclhost"
    MYSQL_PORT: int = 3306
    MYSQL_DB_NAME: str = "grapefruit"
    MYSQL_USER: str = "root"
    MYSQL_PASSWORD: str = "123456"

    # ================================================= #
    # ******************** Redis配置 ******************* #
    # ================================================= #
    REDIS_HOST: str = "loaclhost"
    REDIS_PORT: int = 6379
    REDIS_DB_NAME: int = 0
    REDIS_USER: str = "default"
    REDIS_PASSWORD: str = "123456"
    REDIS_PREFIX_NAME: str = "lemon"         # redis前缀名

    @property
    def LOGGER_CONFIG(self) -> Dict[str, Any]:
        """获取日志配置"""
        return {
            "sink": self.LOGGER_SINK,
            "level": self.LOGGER_LEVEL,
            "format": self.LOGGER_FORMAT,
            "intercept": self.LOGGER_INTERCEPT
        }


    @property
    def FASTAPI_CONFIG(self) -> Dict[str, Union[str, bool, None]]:
        """获取FastAPI应用属性"""
        return {
            "debug": self.DEBUG,
            "title": self.TITLE,
            "version": self.VERSION,
            "description": self.DESCRIPTION,
            "summary": self.SUMMARY,
            "root_path": self.ROOT_PATH,
            "root_path_in_servers": self.ROOT_PATH_IN_SERVERS,
            "docs_url": None,
            "redoc_url": None
        }

    @property
    def UVICORN_CONFIG(self) -> Dict[str, Any]:
        """获取Uvicorn配置"""
        return {
            "host": self.SERVER_HOST,
            "port": self.SERVER_PORT,
            "reload": self.RELOAD,
            "factory": self.FACTORY,
            "workers": self.WORKERS,
            "access_log": self.ACCESS_LOG,
        }

    @property
    def MYSQL_CONFIG(self) -> Dict[str, Union[str, bool, None]]:
        """获取MYSQL的连接配置"""
        return {
            "host": self.MYSQL_HOST,
            "port": self.MYSQL_PORT,
            "db": self.MYSQL_DB_NAME,
            "username": self.MYSQL_USER,
            "password": self.MYSQL_PASSWORD
        }

    @property
    def ORM_CONFIG(self) -> Dict[str, Union[str, bool, None]]:
        """获取MYSQL的连接配置"""
        config = {
            "connections": {},
            "apps": {
                "models": {
                    "models": self.ORM_MODELS,
                    "default_connection": "default",
                },
            },
            "use_tz": False,  # Whether to use timezone-aware datetimes
            "timezone": "Asia/Shanghai",  # Timezone setting
        }
        if self.ORM_ENGINE == "mysql":
            connections = {
                "default": {
                    "engine": "tortoise.backends.mysql",
                    "credentials": {
                        "host": self.MYSQL_HOST,  # Database host address
                        "port": self.MYSQL_PORT,  # Database port
                        "user": self.MYSQL_USER,  # Database username
                        "password": self.MYSQL_PASSWORD,  # Database password
                        "database": self.MYSQL_DB_NAME,  # Database name
                    },
                    "maxsize": 20,  # 连接池大小
                }
            }
            config["connections"] = connections
        else:
            connections = {
                "default": {
                    "engine": "tortoise.backends.sqlite",
                    "credentials": {
                        "file_path": f"{self.SQLITE_DB_PATH}/{self.SQLITE_DB_NAME}" # Path to SQLite database file
                    },  
                }
            }
            config["connections"] = connections
        return config


    @property
    def REDIS_CONFIG(self) -> str:
        """获取REDIS的连接配置"""
        return {
            "host": self.REDIS_HOST,
            "port": self.REDIS_PORT,
            "db": self.REDIS_DB_NAME,
            "username": self.REDIS_USER,
            "password": self.REDIS_PASSWORD
        }

    @property
    def REDIS_URL(self) -> str:
        """获取REDIS的连接配置"""
        return f"redis://{self.REDIS_USER}:{self.REDIS_PASSWORD}@{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB_NAME}"
        

@lru_cache(maxsize=1)
def get_settings() -> Settings:
    """获取配置实例"""
    env = os.getenv('ENVIRONMENT', EnvironmentEnum.DEV.value)
    if env not in [e.value for e in EnvironmentEnum]:
        raise ValueError(f"无效的环境配置: {env}")
    
    env_file = f"env/.env.{env}"
    if not os.path.exists(env_file):
        raise FileNotFoundError(f"环境配置文件不存在: {env_file}")
    return Settings(_env_file=env_file)


config = get_settings()